Developing Optimal CUDA Kernels on Hopper Tensor Cores

Pradeep Ramani, Cris Cecka | March 22, 2023

目录

CUTLASS 简介

CUTLASS (CUDA C++ Template Library for Deep Learning and High Performance Computing) 是一个用于在各种范围和规模上进行矩阵计算的优化 CUDA C++ 模板库。

Page 2 - CUTLASS 概览,展示了其在不同抽象层级(设备、内核、集合、原子、线程、架构内在函数)的功能。
Page 2 - CUTLASS 概览,展示了其在不同抽象层级(设备、内核、集合、原子、线程、架构内在函数)的功能。

关键信息:
- 开源: https://github.com/NVIDIA/cutlass (new BSD license)
- 最新版本: CUTLASS 3.0
- 文档: https://github.com/NVIDIA/cutlass#documentation
- 功能: https://github.com/NVIDIA/cutlass/blob/master/media/docs/functionality.md
- 历届 GTC 演讲: GTC'18, GTC'19, GTC'20, GTC'21, GTC'22

NVIDIA Hopper 上的 Tensor Core 性能

使用 CUTLASS 3.0 和 CUDA 12.0 Toolkit 在 NVIDIA H100 上的性能表现。下图展示了在不同 GPU 架构(A100, A40, H100, L40)上,各种 GEMM (通用矩阵乘法) 配置的相对峰值性能。结果显示,Hopper 架构(H100, L40)在多种精度和数据类型下均能达到接近理论峰值的性能。

Page 3 - CUTLASS 3.0 GEMM 相对峰值性能对比图。
Page 3 - CUTLASS 3.0 GEMM 相对峰值性能对比图。

发展路线图 (Roadmap)

以下是 CUTLASS 在 2023 年的开发路线图,可能会有变动。

Page 4 - CUTLASS v2.x, v3.x, 及 Python (v3.x) 在 2023 年四个季度的开发路线图。
Page 4 - CUTLASS v2.x, v3.x, 及 Python (v3.x) 在 2023 年四个季度的开发路线图。

议程 (Agenda)

本次演讲将涵盖以下主题:
- Hopper 架构 (Hopper Architecture)
- CuTe
- CUTLASS 3.0
- CUTLASS Python
- 结论 (Conclusion)

NVIDIA Hopper 架构

NVIDIA H100 引入了多项架构改进,以提升性能。

Page 7 - NVIDIA Hopper 架构的主要特性,包括新的 Tensor Core 指令、线程块集群、额外数据类型和使用 TMA 的异步复制。
Page 7 - NVIDIA Hopper 架构的主要特性,包括新的 Tensor Core 指令、线程块集群、额外数据类型和使用 TMA 的异步复制。

主要特性

更多细节请参阅 "NVIDIA H100 Tensor Core GPU Architecture" 白皮书。

Hopper 架构 - Tensor Core 运算性能

下表比较了 Hopper (H100)、Ampere (A100) 和 Volta (V100) 架构上 Tensor Core 运算的理论峰值 TFLOPS。Hopper 架构在所有数据类型上都展现出显著的性能飞跃。

Page 8 - Hopper、Ampere 和 Volta 架构的 Tensor Core 运算性能 (TFLOPS) 对比表。
Page 8 - Hopper、Ampere 和 Volta 架构的 Tensor Core 运算性能 (TFLOPS) 对比表。

Tensor Core 运算: 基本形态

Tensor Core 的核心是矩阵乘加运算:D = op(A, B) + D

Page 9 - Tensor Core M-by-N-by-K 矩阵运算的基本形态示意图。
Page 9 - Tensor Core M-by-N-by-K 矩阵运算的基本形态示意图。

F16 * F16 + F32 运算示例

下图展示了一个 64-by-N-by-16 形态的 F16 乘法与 F32 累加操作的示例,并给出了对应的 wgmma.mma_async 指令的汇编代码。

Page 10 - F16*F16+F32 运算指令 wgmma.mma_async 及其汇编代码示例。
Page 10 - F16*F16+F32 运算指令 wgmma.mma_async 及其汇编代码示例。

新的数据移动方式:使用 TMA 的异步复制

Hopper 架构引入了 Tensor Memory Accelerator (TMA) 来实现一种新的高效数据移动方式。

TMA 多播 (Multicast) 可视化

TMA 支持将数据从全局内存高效地多播到块集群 (Block Cluster) 内的多个 SM (Streaming Multiprocessor)。一个 SM 的 TMA 从全局内存读取数据后,可以将数据和屏障更新直接多播给同一集群中的其他 SM,从而避免了重复的全局内存读取。

Page 15 - TMA 多播机制示意图,展示了一个 SM 的 TMA 将数据从全局内存多播到另一个 SM。
Page 15 - TMA 多播机制示意图,展示了一个 SM 的 TMA 将数据从全局内存多播到另一个 SM。

copy.async.bulk

copy.async.bulk 是一系列指令,用于发出一个 warp 统一的异步复制操作。它支持 2D、平铺模式(tiled mode)和多播(multicast)。

`copy.async.bulk` 指令介绍与汇编示例 - Page 16
`copy.async.bulk` 指令介绍与汇编示例 - Page 16

CuTe

什么是 CuTe?

CuTe 是一个用于 CUDA Tensors 的库。

CuTe 简介 - Page 18
CuTe 简介 - Page 18

为什么需要 CuTe?

因为布局 (Layouts) 和张量 (Tensors) 无处不在。

从 CUTLASS 2.x 到 3.x 的演进,体现了从大量特定的、硬编码的布局类型(如 RowMajor, ColumnMajor, TensorNCHW 等)到一个统一的、可组合的 Layout<Shape, Stride> 抽象的转变,极大地简化了代码。

CuTe 的重要性及 CUTLASS 2.x 与 3.x 的对比 - Page 19
CuTe 的重要性及 CUTLASS 2.x 与 3.x 的对比 - Page 19

CuTe in CUTLASS-3.0

在 CUTLASS 3.0 中,CuTe 的应用主要体现在以下几个方面:

CuTe在CUTLASS-3.0中的应用 - Page 20
CuTe在CUTLASS-3.0中的应用 - Page 20

布局 (Layouts) 将坐标映射到存储

布局定义了一个函数,它将逻辑上的多维坐标映射到线性的物理存储地址。下图展示了对于一个形状为 (4,3) 的逻辑张量,不同的布局函数(行主序、列主序、带填充、混合模式)如何将其映射到一维内存空间。

布局映射示例 - Page 21
布局映射示例 - Page 21

布局表示 (Layout Representation)

布局可以通过形状 (Shapes)步幅 (Strides) 来表示。内存中的偏移量可以通过坐标与步幅的内积计算得出:f(coord) = inner_product(coord, stride)

下图展示了不同的形状和步幅组合如何产生不同的内存布局。

使用形状和步幅表示布局 - Page 22
使用形状和步幅表示布局 - Page 22

分层布局 (Hierarchical Layouts)

张量可以具有分层的形状和折叠的模式。一个逻辑上具有分层形状的张量可以被“折叠”并视为一个简单的矩阵,这有助于简化操作和理解。

分层布局示例 1 - Page 23
分层布局示例 1 - Page 23
分层布局示例 2 - Page 24
分层布局示例 2 - Page 24
分层布局示例 3(嵌套形状) - Page 25
分层布局示例 3(嵌套形状) - Page 25

核心设计要素 (Key design ingredients)

CuTe Tensors 的核心设计要素包括:

CuTe Tensors 的核心设计要素 - Page 26
CuTe Tensors 的核心设计要素 - Page 26

布局映射 (Layout Mappings)

布局定义了从逻辑坐标到线性索引的完整映射流程。

  1. 逻辑 1-D 坐标 (e.g., A(I))
  2. 通过坐标映射 (Coordinate Mapping) 转换为 逻辑 n-D 坐标 (e.g., A(i,j))
  3. 通过坐标映射 (Coordinate Mapping) 转换为 逻辑 h-D (分层) 坐标 (e.g., A(i,(j1,j2)))
  4. 通过索引映射 (Index Mapping) 转换为 线性 1-D 存储索引 (e.g., A[k])

  5. Shape 定义了坐标映射: (I) ⇔ (i,j) ⇔ (i,(j1,j2))

  6. Stride 定义了索引映射: (i,(j1,j2)) ⇔ [k]
布局映射流程图 - Page 27
布局映射流程图 - Page 27

布局示例 (Example Layout)

以下是一个使用 CuTe 构建复杂布局的示例。

CuTe 布局、索引和切片示例 - Page 28
CuTe 布局、索引和切片示例 - Page 28

布局转写示例 (Layout Transcription Examples)

CuTe 的 Layout<Shape, Stride> 抽象能够表示许多传统和复杂的内存布局。

常见布局的 CuTe 表示法 - Page 29
常见布局的 CuTe 表示法 - Page 29

Swizzle 布局示例 (Swizzle Layout Examples)

Swizzle 布局通过重排数据来优化内存访问模式,以减少缓存冲突和提高带宽利用率,这在 GPU 编程中非常常见。CuTe 同样可以简洁地表示这些复杂的布局。

Swizzle 布局的 CuTe 表示法 - Page 30
Swizzle 布局的 CuTe 表示法 - Page 30

组合能力 (Composition Power) 示例

幻灯片通过一个逐步构建的示例来阐述“组合能力”的概念。

首先,我们有一个一维的逻辑数据数组。

Page 31: 初始一维数组
Page 31: 初始一维数组

接着,对这个数组进行分区,定义了值的布局。此布局由 ((2,3))((1,4)) 这样的形状元组以及一个具体的值索引表 Values 来描述。

Page 33: 值的布局定义
Page 33: 值的布局定义

然后,引入了第二层分区,将不同的值集(以不同颜色表示)分配给不同的线程。

Page 35: 多层分区与值表
Page 35: 多层分区与值表

这个多层分区是通过线程布局来定义的。Threads 布局由 ((2, 2))((2, 12)) 等元组描述。这建立了一个从线程ID(tid)和值ID(vid)到最终数据坐标(coord c)的映射函数。

Page 37: 线程与值的映射关系
Page 37: 线程与值的映射关系

这个过程的核心思想是函数组合。线程布局(Threads)和值布局(Values)可以被看作两个独立的函数。将它们组合起来,就可以得到一个将数据划分到不同线程的最终布局。

Page 38: 布局的组合操作
Page 38: 布局的组合操作

在代码实现中,这个过程表现为:
1. 创建一个输入张量(make_tensor)。
2. 将输入张量与一个线程-值(thr_val)布局进行组合(composition),生成一个统一的线程-值视图(input_TV)。
3. 通过线程ID(tid)对这个组合视图进行切片,从而得到每个线程负责的数据子集(thr_input)。

Page 39: 组合与切片的代码实现
Page 39: 组合与切片的代码实现

核心思想总结:给定一个从(线程,值)到坐标的映射,分区(Partitioning)本质上就是函数组合(Functional Composition)后进行切片(Slicing)。

Page 40: 组合能力的核心思想总结
Page 40: 组合能力的核心思想总结

MMA 特征 (MMA Traits)

这部分内容定义了不同NVIDIA GPU架构上矩阵乘累加(MMA)操作的元数据和内存布局。这些定义(Traits)封装了特定硬件指令的细节。

Volta FP16 8x8x4 元数据

MMA_Traits 结构体为Volta架构(SM70)上的 8x8x4 FP16 MMA操作定义了元数据。
- MMA形状 (Shape_MNK): 8x8x4
- 线程网格 (ThrID): 4x2
- 数据类型: 输入为 half_t,累加器为 float
- 布局 (Layouts): 为矩阵A、B、C定义了数据在线程和寄存器中的具体布局。例如,ALayout 将 (T8, V4) 映射到 (M8, K4),意味着8个线程和4个值构成了矩阵A的一个8x4的块。

Page 41: Volta FP16 8x8x4 MMA Traits 定义及布局可视化
Page 41: Volta FP16 8x8x4 MMA Traits 定义及布局可视化

Ampere FP64 8x8x4 元数据

为Ampere架构(SM80)上的 8x8x4 FP64 MMA操作定义了元数据。
- MMA形状 (Shape_MNK): 8x8x4
- 线程数 (ThrID): 32
- 数据类型: 输入和累加器均为 double
- 布局 (Layouts): ALayout 将 (T32, V1) 映射到 (M8, K4)。

Page 42: Ampere FP64 8x8x4 MMA Traits 定义及布局可视化
Page 42: Ampere FP64 8x8x4 MMA Traits 定义及布局可视化

Ampere FP16 16x8x8 元数据

为Ampere架构(SM80)上的 16x8x8 FP16 MMA操作定义了元数据。
- MMA形状 (Shape_MNK): 16x8x8
- 线程数 (ThrID): 32
- 数据类型: 输入为 half_t,累加器为 float
- 布局 (Layouts): ALayout 将 (T32, V4) 映射到 (M16, K8)。

Page 43: Ampere FP16 16x8x8 MMA Traits 定义及布局可视化
Page 43: Ampere FP16 16x8x8 MMA Traits 定义及布局可视化

Hopper FP16 64x16x16 元数据

为Hopper架构(SM90)上的 64x16x16 FP16 MMA操作定义了元数据。此定义使用了更通用的 GMMA (可能指代 Generic MMA) 模板。
- MMA形状 (Shape_MNK): 64x16x16
- 线程数 (ThrID): 128
- 数据类型: 输入为 half_t,累加器为 float
- 布局 (Layouts): 使用 GMMA::ABLayout 等更高级的抽象来定义,以适应Hopper架构的特性。

Page 44: Hopper FP16 64x16x16 MMA Traits 定义及布局可视化
Page 44: Hopper FP16 64x16x16 MMA Traits 定义及布局可视化

布局代数 (Layout Algebra)

Layout Algebra 定义了一套在布局上进行操作的代数法则,允许以声明式的方式构建和变换复杂的内存布局。

逻辑积 (Logical Product)

公式: f_A ⊗ g_B = (f_A ∘ g_B) → (f_A, h_B')

描述: "生成一个布局,其中布局B的每个元素都是一个布局A。" 这是一种创建分块或瓦片式布局的操作。常见的操作包括 logical_productblocked_productraked_producttile_to_shape

Page 45: 逻辑积 (Logical Product) 的定义与示例
Page 45: 逻辑积 (Logical Product) 的定义与示例

逻辑除 (Logical Divide)

公式: f_A ⊘ g_B = f_A ∘ (g_B, g_B*) → (h_B', l_C)

描述: "将布局A拆分为由布局B指向的元素和其他剩余部分。" 这是一种对布局进行解构或分区的操作,与逻辑积互逆。常见的操作包括 logical_dividezipped_dividetiled_divide

Page 45: 逻辑除 (Logical Divide) 的定义与示例
Page 45: 逻辑除 (Logical Divide) 的定义与示例

更多关于CuTe库的讨论和示例,请参阅其官方文档:
https://github.com/NVIDIA/cutlass/tree/master/media/docs/cute

CUTLASS 3.0

CUTLASS 3.0 的新特性

images/page-0047.jpg
images/page-0047.jpg

CUTLASS 3.1:
- 针对 TF32 的寄存器支持的 WGMMA (Warp Group Matrix Multiply Accumulate) 内核。
- 用于 CUTLASS 的全新 Pythonic 接口。
- 具有融合功能的高效 Epilogue。

CUTLASS 3.0:
- 利用 CuTe 后端进行了一次重大的重构。
- 高效的 Hopper Tensor Core 指令与使用 TMA (Tensor Memory Accelerator) 的异步拷贝。
- Warp Specialized(Warp 特化)和 Persistent(持久化)内核实现。
- Collective Builders、文档、性能分析器支持、PyCUTLASS 集成、SDK 示例等。

CUTLASS 2.11:
- 针对 Ampere 内核的 Fused MHA(多头注意力)。
- Stream-K - 一个新的通用 Split-K 实现。
- 支持新 Hopper 双精度指令的 BLAS3 功能。

NVIDIA Hopper 上的 Tensor Core 性能

images/page-0048.jpg
images/page-0048.jpg

以下图表展示了使用 CUTLASS 3.0、CUDA 12.0 Toolkit 在 NVIDIA H100 上的 Tensor Core 性能。实验中 m=2048, n=8848。

分块 GEMM (Blocked GEMM) 回顾

Page 49
Page 49

传统的通用矩阵乘法(GEMM)采用分块、分层的模型,在共享内存(Shared Memory)和寄存器(Registers)中复用数据。数据流如下:
全局内存 (Global Memory) -> 共享内存 (Shared Memory) -> 寄存器文件 (Register File) -> CUDA/Tensor Cores -> SMEM -> CUDA Cores -> 全局内存 (Global Memory)。

更多关于此模型的详细信息,请参见 CUTLASS GTC 2018 和 2020 的演讲。

Hopper 架构带来的变化

Page 50
Page 50

在 Hopper 架构中,数据流发生了变化。它采用了线程块集群分块(Block Cluster Tiled),实现了全局内存的大块数据拷贝,并直接从共享内存中复用数据。
新的数据流如下:
全局内存 (Global Memory) -> 共享内存 (Shared Memory) -> Tensor Cores -> CUDA Cores -> SMEM -> 全局内存 (Global Memory)。

CUTLASS 3 的概念性 GEMM 层次结构

CUTLASS 3 的层次结构不再以硬件层次为中心。

Page 52
Page 52

上图展示了 CUTLASS 3 的概念性 GEMM 层次结构:

CUTLASS 3.x API 入口点

CUTLASS 3.x 减少了 API 的表面积。

Page 53
Page 53

CUTLASS 3: 内核 API

cutlass::gemm::kernel::GemmUniversal<>

以下调度策略示例展示了 Warp 特化的主循环如何与持久化和非持久化内核调度组合:

template<
  int Stages_,
  class ClusterShape_ = Shape<_1, _1, _1>,
  class KernelSchedule = KernelTmaWarpSpecialized // or KernelTmaWarpSpecializedPersistent
>
struct MainloopSm90TmaWarpSpecialized {
  constexpr static int Stages = Stages_;
  using ClusterShape = ClusterShape_;
  using ArchTag = arch::Sm90;
  using Schedule = KernelSchedule;
};
Page 54
Page 54

CUTLASS 3: 集合 API

cutlass::gemm::collective::Gemm<>
cutlass::epilogue::collective::Epilogue<>

// n-buffer in smem, pipelined with Hopper GMMA and TMA
template<
  int Stages_,
  class ClusterShape_ = Shape<_1, _1, _1>,
  int PipelineAsyncMmaStages_ = 1
>
struct MainloopSm90TmaGmma {
  constexpr static int Stages = Stages_;
  using ClusterShape = ClusterShape_;
  constexpr static int PipelineAsyncMmaStages = PipelineAsyncMmaStages_;
  using ArchTag = arch::Sm90;
  using Schedule = KernelTma;
};

// n-buffer in smem, pipelined with Hopper GMMA and TMA, warp-specialized
template<
  int Stages_,
  class ClusterShape_ = Shape<_1, _1, _1>,
  class KernelSchedule = KernelTmaWarpSpecialized
>
struct MainloopSm90TmaGmmaWarpSpecialized {
  constexpr static int Stages = Stages_;
  using ClusterShape = ClusterShape_;
  using ArchTag = arch::Sm90;
  using Schedule = KernelSchedule;
};
Page 55
Page 55

CUTLASS 3: 集合构建器 (Collective Builders)

cutlass::gemm::collective::CollectiveBuilder<>

示例 1: "我只想要一个 Hopper 主循环"

using CollectiveOp = typename cutlass::gemm::collective::CollectiveBuilder<
  arch::Sm90, arch::OpClassTensorOp,
  half_t, LayoutA, 8,
  half_t, LayoutB, 8,
  float,
  Shapes<_128, _128, _64>, Shapes<_1, _2, _1>,
  gemm::collective::StageCountAuto,
  gemm::collective::KernelScheduleAuto
>::CollectiveOp;

示例 2: "我想要一个 Hopper 主循环,但使用持久化调度和 5 个阶段"

using CollectiveOp = typename cutlass::gemm::collective::CollectiveBuilder<
  arch::Sm90, arch::OpClassTensorOp,
  half_t, LayoutA, 8,
  half_t, LayoutB, 8,
  float,
  Shapes<_128, _128, _64>, Shapes<_1, _2, _1>,
  gemm::collective::StageCount<5>,
  gemm::KernelTmaWarpSpecializedPersistent
>::CollectiveOp;
Page 56
Page 56

实现峰值性能的秘诀

异步机器的攻击

Page 57
Page 57

异步流水线 (Async. Pipelines)

管理到达等待 (Arrive Wait) 和事务屏障 (Transaction Barriers)

PipelineTmaAsync 模板类接口示例:

template <int Stages, class ClusterShape>
class PipelineTmaAsync {
  // Acquire a stage in Smem before writing to it
  void producer_acquire(PipelineStage<Stages> state);

  // Commit a stage after writing to Smem (optional)
  void producer_commit(PipelineStage<Stages> state);

  // Wait for Commit before consuming a stage in Smem
  void consumer_wait(PipelineStage<Stages> state);

  // Notify end of consumption of Smem stage
  void consumer_release(PipelineStage<Stages> state);
};
Page 58
Page 58

异步 Warp 特化/专用内核 (Async. Warp Specialized Kernel)

共享多处理器 (Shared Multiprocessor) 的逻辑视图

该内核设计将 SM (Shared Multiprocessor) 内的 Warp 分为两类:
- MMA Warps: 负责执行矩阵乘加 (Matrix Multiply-Accumulate) 计算。
- DMA Warps: 负责通过张量内存加速器 (Tensor Memory Accelerator, TMA) 进行数据移动 (Direct Memory Access)。

Page 59 - 逻辑视图
Page 59 - 逻辑视图

数据加载流程 (Producer):

  1. 发起异步拷贝: DMA Warps 发起 cp.async.bulk 指令,通过 TMA 从全局内存 (Global Memory) 异步加载数据。同时,它们会在共享内存 (Shared Memory) 上获取一个异步屏障 (Async. Barrier) 的所有权,为即将写入的数据块做准备。

    Page 61
    Page 61
  2. 数据到达: TMA 完成从全局内存的数据读取,并将数据写入共享内存。同时,它会更新对应的屏障状态,以通知等待该数据的消费者。此操作支持将数据和屏障更新多播 (Multicast) 到另一个线程块。

    Page 62
    Page 62

计算流程 (Consumer):

  1. 等待数据: MMA Warps 在共享内存的异步屏障上执行 Wait 操作,暂停执行,直到 DMA Warps 加载的数据准备就绪。

    Page 63
    Page 63
  2. 执行计算: 一旦屏障被满足,MMA Warps 被唤醒。它们发起 wgmma.mma_async (Warp Group MMA Asynchronous) 指令,让张量核心 (Tensor Cores) 从共享内存中读取操作数并开始计算。

    Page 64
    Page 64
  3. 释放屏障: 计算结果被写入寄存器内存 (Register Memory)。wgmma 操作完成后,MMA Warps 会释放 (Release) 异步屏障,表明它们已经消耗完共享内存中的数据。这块共享内存区域现在可以被 DMA Warps 用于加载下一批数据,从而实现流水线操作。

    Page 65
    Page 65

数据写回流程 (Epilogue):

  1. 存储到共享内存: 计算结果从寄存器内存通过 stmatrix 指令存储回共享内存。

    Page 66
    Page 66
  2. 异步写回全局内存: MMA Warps 发起 copy.bulk.async 指令,通过 TMA 将共享内存中的最终结果异步写回到全局内存。

    Page 67
    Page 67

完整流程总结:
下图展示了使用异步屏障的完整生产者-消费者模型。DMA Warps (生产者) 负责从全局内存加载数据到共享内存,并通过屏障通知 MMA Warps (消费者)。MMA Warps 等待数据就绪,然后使用张量核心进行计算,并将结果写回。整个过程是异步流水线化的,以最大化计算和数据传输的重叠。

Page 68
Page 68

紧凑的主循环表示 (Compact Mainloop Representation)

下图展示了 DMA 和 MMA 主循环的伪代码表示,体现了生产者-消费者模式。

Page 69
Page 69

持久化 Warp 专门化 (Persistent Warp Specialization)

这是一种隐藏非张量核心操作开销的方法。

Page 70
Page 70

Warp 专门化和持久化内核

下图展示了这种模式:一个生产者 (Producer, DMA Warps) 持续通过 TMA 准备数据,而多个消费者 (Consumers, MMA Warps) 并行地进行张量核心计算和后序处理,实现了高度流水化的执行。

Page 71
Page 71

CUTLASS Python

CUTLASS Python 接口

Page 73
Page 73

目标:简化 CUTLASS 内核的声明、生成和编译

下图对比了 C++ 和 Python 接口的易用性。C++ 接口使用复杂的模板元编程,代码冗长且难以理解。而 Python 接口提供了一种更简洁、更具声明性的方式来构建和配置内核,例如可以轻松地更改 swizzling_functor 或添加 relu 激活函数。

Page 74
Page 74

目标:在 Python 中捕获常见的编译和运行时错误

下图展示了错误处理方面的改进。C++ 模板编译错误通常非常冗长且晦涩难懂,给调试带来巨大困难。而 Python 接口能在运行时抛出清晰、易于理解的异常,明确指出不支持的操作、数据类型或布局组合,极大地改善了开发体验。

Page 75
Page 75

与深度学习框架(如 PyTorch)的轻松集成

目标是实现与深度学习框架(如 PyTorch)的轻松集成。通过 CUTLASS Python 接口,可以定义一个计算计划(plan),然后生成相应的 PyTorch 扩展。

具体流程如下:

  1. 定义计划:使用 cutlass.GroupedGemm 等类来定义所需的计算操作,例如指定元素类型为 torch.float16 和布局为行主序。
  2. 代码生成:调用 cutlass.emit.pytorch 函数,传入构建好的计划,以生成 PyTorch 扩展所需的源代码文件。这会创建 Python (setup.py)、C++ (grouped_gemm.cpp) 和 CUDA (grouped_gemm.cu) 文件。
  3. 编译安装:在命令行中运行 python setup.py install 来编译和安装生成的扩展。
  4. 在 Python 中使用:安装完成后,可以直接在 Python 脚本中 import 该模块,并像调用普通 Python 函数一样运行高性能的 CUTLASS 内核。
Page 76
Page 76

结论

本报告对 CUTLASS 及其最新进展进行了总结。

CUTLASS 路线图
- CUTLASS 2.11 于 2022 年 11 月发布,将作为最后一个 CUTLASS 2.x 系列的版本。
- CUTLASS 3.0 于 2023 年 1 月发布。
- CUTLASS 3.1 预计于 2023 年 4 月可用。

CUTE
- CUTE 是一种思考张量 (Tensor) 和布局 (Layout) 的新方式。
- 它极大地简化了地址计算逻辑。
- CUTE 是 CUTLASS 3 的后端。

CUTLASS 3.0
- 为用户提供了灵活的抽象,用于组合自定义的内核和集合操作 (collectives)。
- 使用第四代张量核心 (Tensor Cores) 实现最优计算。
- 支持异步持久化 (async Persistent) 的生产者-消费者同步模型。
- 开源代码库:https://github.com/NVIDIA/cutlass

Page 78
Page 78

致谢 (Acknowledgements)

参考文献

NVIDIA Hopper 架构与 CUDA
- "Inside the NVIDIA Hopper Architecture" (GTC 2022)
- "CUDA New Features and Beyond" (GTC 2022, GTC 2023)
- "Optimizing Applications for Hopper Architecture" (GTC 2023)
- "NVIDIA Hopper Architecture In-Depth" (博客文章)

PTX ISA
- 使用并行线程执行 (Parallel Thread Execution) 和指令集架构的编程指南 (CUDA 文档)。

CUTLASS
- https://github.com/NVIDIA/cutlass (开源软件,New BSD 许可证)
- CUTLASS Parallel For All 博客文章
- 往届 GTC CUTLASS 演讲:GTC'18, GTC'19, GTC'20, GTC'21, GTC'22, GTC'22

Page 79
Page 79
Page 80
Page 80